import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
import { Geometry } from 'three/examples/jsm/deprecated/Geometry.js';
import { CSM } from 'three/examples/jsm/csm/CSM.js';
import TWEEN from '@tweenjs/tween.js';
import * as d3 from 'd3';
import { ref } from 'vue';

import { GUI } from "three/examples/jsm/libs/dat.gui.module";
import useCSS2DRender from "./hooks/useCSS2DRender"




// 坐标转换
const projection = d3
  .geoMercator()
  .center([106.0, 39.5])
  .scale(950)
  .translate([-18, -225]);

const vs = `
varying vec2 vUv;
void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`;
const fs = `
uniform sampler2D baseTexture;
uniform sampler2D bloomTexture;
varying vec2 vUv;
void main() {
  gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
}
`;
// 初始化gui
const initGui = () => {
  const gui = new GUI()
  const guiParams = {
    topColor: "#b4eeea",
    sideColor: "#123024",
    scale: 0.1,
  }
  var params = new function () {
    this.color = 0x00ff00; //颜色
    this.size = 1; //粒子大小

  };
  gui.addColor(params, "color").onChange(e => { //点击颜色面板，e为返回的10进制颜色
    console.log("color changed. ", e);
  });
  // 设置 GUI 控件的 Z 轴层级为较大的值，确保其位于其他元素之上
  gui.domElement.style.zIndex = "9999";

  // 设置 GUI 控件的位置
  gui.domElement.style.position = "absolute";
  gui.domElement.style.left = "10%"; // 将 GUI 控件水平居中
  gui.domElement.style.top = "5%"; // 将 GUI 控件垂直居中
  // gui.domElement.style.transform = "translate(-50%, -50%)"; // 通过 transform 属性进行居中对齐



}



const { initCSS2DRender, create2DTag } = useCSS2DRender()
var css2dRender;
var controls;

var meshArea = null
var meshOld = null
var meshFlag = 0
var startTime = performance.now(); // 获取当前时间  
var duration = 1000; // 动画持续时间，单位毫秒  
var amountToRaise = 0.3; // 你想要改变的高度量  

// 创建一个半透明的蓝色材质  
const materialBlue = new THREE.MeshBasicMaterial({
  color: 0x3f9fae, // 蓝色  
  transparent: true, // 启用透明  
  opacity: 0.95 // 设置透明度为50%  
});

// 创建材质，用于地图部分
const materialDeepBlue = new THREE.MeshBasicMaterial({
  color: `#1E293B`, // 设置颜色
  transparent: true, // 开启透明
  opacity: 1, // 设置不透明度
});


function Render3DMode(idNames = 'three-frame', idDataBoxNames='dataViewBox') {
  // 旋转半圆 
  let half_circle_blue_;
  let blue_bottom_circle;

  // 在全局定义变量用于控制波动效果的参数
  let time = 0;
  const speed = 0.01;
  const amplitude = 0.1;

  // 环形光圈
  let circleRing;
  let littleCircleRing;

  // 创建一个数组来保存文字对象
  let textMeshArray = [];

  let renderer, sence, camera, bloomComposer, finalComposer;
  const BLOOM_LAYER = 1;
  const bloomLayer = new THREE.Layers();
  bloomLayer.set(BLOOM_LAYER);
  const centerLatlng = ref({});
  const materials = {};
  const darkMaterials = {};
  let idName = ref(idNames);
  let idDataBoxName = ref(idDataBoxNames);
  const darkMaterial = new THREE.MeshBasicMaterial({ color: 'black' });

  const province = new THREE.Object3D();  // 省份
  const meshArray = []; // 用于存储每个省份的 mesh

  const raycaster = new THREE.Raycaster(); // 创建一个 Raycaster 对象
  const mouse = new THREE.Vector2(); // 创建一个二维向量存储鼠标点击位置
  window.addEventListener('click', onClick, false); // 监听鼠标点击事件

  function onClick(event) {
    
    const idDataBoxElement = document.getElementById(idDataBoxName.value);

    // 获取 canvas 元素的尺寸
    const canvasElement = document.getElementById(idName.value);
    const canvasWidth = 360; // canvas 实际宽度
    const canvasHeight = 180; // canvas 实际高度

    // 获取 canvas 元素相对于视口左上角的偏移量
    const canvasBounds = canvasElement.getBoundingClientRect();
    const offsetX = canvasBounds.left;
    const offsetY = canvasBounds.top;
    // console.log(event.clientX - offsetX)
    // console.log(event.clientY - offsetY)
    // 计算归一化设备坐标
    mouse.x = ((event.clientX - offsetX) / canvasWidth) * 2 - 1;
    mouse.y = -((event.clientY - offsetY) / canvasHeight) * 2 + 1;
    // console.log('x:',((event.clientX - offsetX) / canvasWidth)* 2 - 1)
    // console.log('y:',mouse.y)
    // 更新射线的起点和方向
    raycaster.setFromCamera(mouse, camera);

    // 计算射线与模型的交点
    const intersects = raycaster.intersectObjects(meshArray, true);

    // 如果有交点，表示点击了模型
    if (intersects.length > 0) {
      idDataBoxElement.style.display = 'block';

      // 获取第一个交点的物体
      const clickedObject = intersects[0].object;
      // 将模型颜色设置为透明蓝色
      // clickedObject.material = materialBlue;
      // clickedObject.position.y += 0.3; // 改变的高度量
      meshArea = clickedObject
      if (meshArea == meshOld) {
        idDataBoxElement.style.display = 'none';
        meshFlag = 2
      }

      // 顯示——相關數據
    }
  }

  //  初始化
  const initMaps = () => {
    let { width, height } = { width: 1800, height: 900 };

    // 场景Width and height
    sence = new THREE.Scene();
    sence.fog = new THREE.FogExp2(0x000000, 0.01)
    sence.background = new THREE.Color('#000000');


    // 相机
    camera = new THREE.PerspectiveCamera(
      50,
      window.innerWidth / window.innerHeight,
      0.01,
      1000,
    );
    camera.position.set(30.9, 21.7, 37.4);
    camera.lookAt(0, 0, 0);
    // 渲染器
    renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.shadowMap.enabled = true;
    renderer.shadowMapEnabled = true;
    renderer.shadowMapSoft = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(width, height);  // 大小

    const container = document.getElementById(idName.value)
    document.getElementById(idName.value)?.appendChild(renderer.domElement);

    // 初始化initCSS2DRender
    css2dRender = initCSS2DRender(1800, 900, container)

    // 辉光材质
    const renderPass = new RenderPass(sence, camera);
    const bloomPass = new UnrealBloomPass(
      new THREE.Vector2(
        renderer.domElement.offsetWidth,
        renderer.domElement.offsetHeight,
      ),
      1,
      1,
      0.1,
    );
    bloomPass.threshold = 0;
    bloomPass.strength = 1.6;
    bloomPass.radius = 0;

    bloomComposer = new EffectComposer(renderer);
    bloomComposer.renderToScreen = false;
    bloomComposer.addPass(renderPass);
    bloomComposer.addPass(bloomPass);

    // 普通材质 自定义着色器
    finalComposer = new EffectComposer(renderer);
    const FxaaPass = createFxaaPass();
    const shaderPass = new ShaderPass(
      new THREE.ShaderMaterial({
        uniforms: {
          baseTexture: { value: null },
          bloomTexture: { value: bloomComposer.renderTarget2.texture },
        },
        vertexShader: vs,
        fragmentShader: fs,
        defines: {},
      }),
      'baseTexture',
    ); // 创建自定义的着色器Pass，详细见下
    shaderPass.needsSwap = true;

    finalComposer.addPass(renderPass);
    finalComposer.addPass(shaderPass);
    finalComposer.addPass(FxaaPass);


    addScence();
    addlight();
    CameraAnmition();
    render();
    renderanmi();
    initGui();


  };


  const addLabel = (xy, z, message, name) => {
    const x = xy[0]
    const y = xy[1]
    // 设置标签的显示内容和位置
    var label = create2DTag("标签", "map-32-label")
    sence.add(label)
    label.show('电力: ' + message, new THREE.Vector3(x - 1, z + 1, y))

  }


  // 在渲染循环中更新文字网格的朝向
  function updateTextOrientation(camera) {
    // 遍历数组中的每个文字对象，更新它们的朝向
    textMeshArray.forEach(function (textMesh) {
      textMesh.lookAt(camera.position);
    });
  }

  // 文字
  function add3DFont(xy, message) {
    // console.log('xy:', xy)
    const x = xy[0]
    const y = xy[1]
    new THREE.FontLoader().load('Smiley Sans Oblique_Regular.json', function (font) {
      let textGeo = new THREE.TextGeometry(message, {
        font: font,
        size: 0.6,
        height: 0.3,
      });
      let materials = [
        new THREE.MeshPhongMaterial({ color: 0xFFFFFF, flatShading: true }), // front
        new THREE.MeshPhongMaterial({ color: 0xFFFFFF }) // side
      ];
      let textMesh = new THREE.Mesh(textGeo, materials);
      textMesh.position.set(x, 3.4, y - 1);
      textMesh.castShadow = true
      // 将文本向左旋转45度
      // textMesh.rotation.y = Math.PI / 4;
      // 将文本沿着 X 轴旋转 90 度，使其平躺在地面上
      // textMesh.rotation.x = -Math.PI / 2;
      // 设置文本面向摄像机
      // textMesh.lookAt(camera.position);

      sence.add(textMesh);

      // 将创建的文字对象保存到数组中
      textMeshArray.push(textMesh);

    });
  }
  // 灯光
  const addlight = () => {
    var spotLight = new THREE.AmbientLight(0xcccccc);
    spotLight.position.set(-50, 60, 15);
    // AmbientLight 是一种环境光，不会产生阴影。如果你想要添加产生阴影的光源，应该使用其他类型的光源，比如 DirectionalLight 或 SpotLight。
    // spotLight.castShadow = true; // 让光源产生阴影 
    spotLight.shadowCameraVisible = true;
    // spotLight.shadowMapWidth = spotLight.shadowMapHeight = 1024*4
    sence.add(spotLight);
  };
  // 搭建组件
  const addScence = () => {
    // 添加辅助线-后期可以关闭
    // var axisHelper = new THREE.AxisHelper(500);
    // sence.add(axisHelper);


    setTerritory();   // 几何体集合
    addFloot();
    mouseMove();
  };
  // 发光墙，流体墙
  // 地板
  const addFloot = () => {
    //导入材质
    // var texture = new THREE.ImageUtils.loadTexture('/doms.png');
    var geometry = new THREE.PlaneGeometry(1000, 1000, 1, 1);
    var material = new THREE.MeshBasicMaterial({ color: '#1f2937' });
    var floor = new THREE.Mesh(geometry, material);
    floor.material.side = THREE.DoubleSide;
    floor.rotation.x = 0.5 * Math.PI;
    sence.add(floor);
  };
  // 几何体集合
  const setTerritory = () => {


    // //-------------------- 圆柱1 ——地下的黑色
    const geometry1a = new THREE.CylinderBufferGeometry(29, 29, 1, 100);
    // transparent 设置 true 开启透明
    const material1 = new THREE.MeshStandardMaterial({
      color: '#0F172A',
      transparent: false,
    });
    // 374151 1E293B
    // 使用分层渲染，不管用什么材质对象，都必须克隆 geometry1a.clone()
    const circleY1 = new THREE.Mesh(geometry1a.clone(), material1);
    // 绘制地图时 y轴取反 这里同步
    circleY1.position.set(0, 1, 0);
    circleY1.material.opacity = 1;
    circleY1.scale.set(1, 1, 1);
    circleY1.rotation.y = -0.5 * Math.PI;

    // //--------------- 圆环1  ——最外面的——蓝色

    const geometry4a = new THREE.RingGeometry(31, 31.5, 200);
    // transparent 设置 true 开启透明
    const material4 = new THREE.MeshStandardMaterial({
      side: THREE.DoubleSide,
      color: '#08BACF',
      transparent: true,
      opacity: 0.8,
    });
    const complete_circle_blue = new THREE.Mesh(geometry4a.clone(), material4.clone());
    // 绘制地图时 y轴取反 这里同步
    complete_circle_blue.position.set(0, 0, -0.5);
    complete_circle_blue.scale.set(1, 1, 1);
    complete_circle_blue.scale.multiplyScalar(1.2);
    complete_circle_blue.rotation.x = -0.5 * Math.PI;
    complete_circle_blue.layers.enable(1);

    //半圆环 ——蓝色
    const geometry5a = new THREE.RingGeometry(31.5, 32.7, 200, 0.6, 1, 3);
    // transparent 设置 true 开启透明
    const material5 = new THREE.MeshStandardMaterial({
      side: THREE.DoubleSide,
      color: '#31C2EC',
      transparent: true,
      opacity: 0.8,
    });
    half_circle_blue_ = new THREE.Mesh(geometry5a.clone(), material5.clone());
    // 绘制地图时 y轴取反 这里同步
    half_circle_blue_.position.set(0, 0, -0.5);
    half_circle_blue_.scale.set(1, 1, 1);
    half_circle_blue_.rotation.x = -0.5 * Math.PI;
    half_circle_blue_.layers.enable(1);

    //整圆 circle_gray
    const geometry5b = new THREE.RingGeometry(0, 28.5, 200);
    // transparent 设置 true 开启透明
    const material5a = new THREE.MeshStandardMaterial({
      side: THREE.DoubleSide,
      color: '#6b7280',
      transparent: true,
    });
    const circle_gray = new THREE.Mesh(geometry5b.clone(), material5a.clone());
    // 绘制地图时 y轴取反 这里同步
    circle_gray.position.set(0, 1.6, 0);
    circle_gray.scale.set(1, 1, 1);
    circle_gray.rotation.x = -0.5 * Math.PI;

    //圆环4 ——底层 -黑色   circle_black
    const geometry5r = new THREE.RingGeometry(28, 29, 200);
    // transparent 设置 true 开启透明
    const material5r = new THREE.MeshStandardMaterial({
      side: THREE.DoubleSide,
      color: '#1E293B',
      transparent: true,
    });
    const circle_black = new THREE.Mesh(geometry5r.clone(), material5r.clone());
    // 绘制地图时 y轴取反 这里同步
    circle_black.position.set(0, 1.65, 0);
    circle_black.scale.set(1, 1, 1);
    circle_black.rotation.x = -0.5 * Math.PI;

    //
    blue_bottom_circle = ArcCurveGeometry()
    sence.add(circle_black);
    sence.add(circle_gray);
    sence.add(circleY1);
    sence.add(blue_bottom_circle);
    sence.add(half_circle_blue_);
    sence.add(complete_circle_blue);
    sence.add(rectShape());
    render();
  };
  // 多面圆环
  function rectShape() {
    var geometry = new THREE.TorusGeometry(27, 0.3, 16, 100, 5);
    var material = new THREE.MeshBasicMaterial({ color: '#64748B' });
    var torus = new THREE.Mesh(geometry, material);
    torus.position.set(0, 1.65, 0);
    torus.scale.set(1, 1, 1);
    torus.rotation.x = -0.5 * Math.PI;
    return torus;
  }
  // 椭圆
  function ArcCurveGeometry() {
    var positions: any = [];
    var colors: any = [];
    // 椭圆
    const lineGeometry = new THREE.BufferGeometry();
    var curve = new THREE.EllipseCurve(
      0,
      0, // ax, aY
      30,
      30, // xRadius, yRadius
      0,
      2 * Math.PI, // aStartAngle, aEndAngle
      false, // aClockwise
      0, // aRotation
    );
    var points = curve.getPoints(100);
    lineGeometry.addAttribute(
      'position',
      new THREE.BufferAttribute(new Float32Array(positions), 3, true),
    );
    lineGeometry.addAttribute(
      'color',
      new THREE.BufferAttribute(new Float32Array(colors), 3, true),
    );

    lineGeometry.setFromPoints(points);
    var material = new THREE.LineDashedMaterial({
      color: '#64748B',
      scale: 1.1,
      dashSize: 10,
      gapSize: 10,
    });
    var ellipse = new THREE.Line(lineGeometry, material);
    ellipse.computeLineDistances();
    ellipse.rotation.x = -0.5 * Math.PI;
    ellipse.layers.enable(1);
    return ellipse;
  }
  // 抗锯齿优化
  function createFxaaPass() {
    let FxaaPass = new ShaderPass(FXAAShader);
    const pixelRatio = renderer.getPixelRatio();
    FxaaPass.material.uniforms['resolution'].value.x =
      1 / (window.innerWidth * pixelRatio);
    FxaaPass.material.uniforms['resolution'].value.y =
      1 / (window.innerHeight * pixelRatio);
    FxaaPass.renderToScreen = true;
    return FxaaPass;
  }
  // 鼠标移动
  const mouseMove = () => {
    controls = new OrbitControls(camera, renderer.domElement); //创建控件对象
    controls.addEventListener('change', render);
  };
  // 生成随机整数，范围在0到10之间
  function generateRandomInteger() {
    // 生成0到1之间的随机数，不包括1
    var randomNumber = Math.random();
    // 将随机数乘以11，得到0到10之间的浮点数
    var randomFloat = randomNumber * 5;
    // 将浮点数向下取整，得到0到10之间的整数
    var randomInteger = Math.floor(randomFloat);
    return randomInteger;
  }
  // 创建一个线性渐变的 canvas 元素
  function createGradientTexture() {
    const canvas = document.createElement('canvas');
    canvas.width = 1;
    canvas.height = 5512;
    const context = canvas.getContext('2d');

    // 创建线性渐变
    const gradient = context.createLinearGradient(0, 0, 0, 5512);
    gradient.addColorStop(0.4, '#0B0D1F'); // 控制蓝色渐变的范围
    gradient.addColorStop(1, '#0B0D1F'); // 设置底部颜色为白色

    // 填充 canvas
    context.fillStyle = gradient;
    context.fillRect(0, 0, 1, 5512);

    // 将 canvas 转换为纹理
    const texture = new THREE.CanvasTexture(canvas);
    texture.needsUpdate = true; // 更新纹理

    return texture;
  }

  // 地图
  const setMapDom = (e) => {
    const color = '#008c8c';
    e.forEach((item, index) => {

      let powerNumber = generateRandomInteger();

      add3DFont(projection(item.properties.center), item.properties.name); // 添加3D文字
      addLabel(projection(item.properties.center), 6 + powerNumber, powerNumber + 3, item.properties.name); // 添加标签文字
      let cod = item.geometry.coordinates[0];
      if (item.properties.name) {
        centerLatlng.value[item.properties.name] = item.properties.center;
      }
      // 光柱
      dotBarlight(
        projection(item.properties.center),
        item.properties.name == '湄潭县' ? '#008c8c' : '#008c8c',
        powerNumber,
        item.properties.name
      );
      cod = cod.length > 1 ? [[...cod]] : cod;
      cod.forEach((polygon) => {
        const shape = new THREE.Shape();
        const lineGeometry = new THREE.BufferGeometry();
        const pointsArray = new Array();
        for (let i = 0; i < polygon.length; i++) {
          // projection -- 坐标转化
          let [x, y] = projection(polygon[i]);
          pointsArray.push(new THREE.Vector3(x, -y, 3));
          if (i === 0) {
            shape.moveTo(x, -y);
          }
          shape.lineTo(x, -y);
        }
        // 添加多个线
        lineGeometry.setFromPoints(pointsArray);
        const lineMaterial = new THREE.LineBasicMaterial({
          color: '#23A8F2',
        });
        // 创建线
        let lines = new THREE.Line(lineGeometry, lineMaterial);
        lines.rotation.x = -0.5 * Math.PI;
        lines.position.set(0, 2.4, 0);
        // lines厚度
        lines.scale.set(1, 1, 0.3);
        // lines.layers.enable(1);
        sence.add(lines);

        const extrudeSettings = {
          depth: 4,
          bevelEnabled: false,
          bevelSegments: 1,
          bevelThickness: 0.2,
        };
        const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);


        // const mesh = new THREE.Mesh(geometry, [material, material1]); // 创建 Mesh，使用 geometry 和两个材质作为参数
        const mesh = new THREE.Mesh(geometry, materialDeepBlue); // 创建 Mesh
        mesh.position.set(0, 2, 0); // 设置 Mesh 的位置
        // 地图厚度
        mesh.scale.set(1, 1, 0.3);  // 设置 Mesh 的缩放，调整地图的厚度
        // 给mesh开启阴影
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        mesh._color = color;  // 设置 Mesh 的颜色属性
        mesh.rotation.x = -0.5 * Math.PI; // 旋转 Mesh，调整其朝向
        province.add(mesh);  // 将 Mesh 添加到省份（province）中
        meshArray.push(mesh); // 将 mesh 存储到数组中
      });
    });

    sence.add(province);
    render();
  };
  // 地图描边
  const setmapborder = (e) => {
    const province = new THREE.Object3D();

    e.forEach((item, index) => {
      let cod = item.geometry.coordinates[0];
      cod = cod.length > 1 ? [[...cod]] : cod;
      cod.forEach((polygon) => {
        const shape = new THREE.Shape();
        const lineGeometry = new THREE.BufferGeometry();
        const pointsArray = new Array();
        for (let i = 0; i < polygon.length; i++) {
          // projection -- 坐标转化
          let [x, y] = projection(polygon[i]);
          pointsArray.push(new THREE.Vector3(x, -y, 3));
          if (i === 0) {
            shape.moveTo(x, -y);
          }
          shape.lineTo(x, -y);
        }
        // 添加多个线
        lineGeometry.setFromPoints(pointsArray);
        const lineMaterial = new THREE.LineBasicMaterial({
          color: '#f59e0b',
        });
        // 创建线
        let lines = new THREE.Line(lineGeometry, lineMaterial);
        lines.rotation.x = -0.5 * Math.PI;
        lines.position.set(0, 0.2, 0);
        // 地图厚度
        lines.scale.set(1, 1, 1);
        lines.layers.enable(1);
        sence.add(lines);
      });
    });
    sence.add(province);
    render();
  };
  // 动画集合
  // 波动光圈
  const AnmiRingGeometry = (post, colors) => {
    const [x0, y0, z0] = [...post, 3.5];

    // const geometry2 = new THREE.RingGeometry(0, 0.15, 50);
    // // transparent 设置 true 开启透明
    // const material2 = new THREE.MeshBasicMaterial({
    //   color: colors,
    //   side: THREE.DoubleSide,
    //   transparent: true,
    // });
    // circleRing = new THREE.Mesh(geometry2, material2);
    // // 绘制地图时 y轴取反 这里同步
    // circleRing.position.set(x0, z0, y0);
    // circleRing.scale.set(2, 2, 1);
    // circleRing.rotation.x = -0.5 * Math.PI;
    // sence.add(circleRing);

    // 小-圆环
    const geometry3 = new THREE.RingGeometry(0.25, 0.3, 6);
    // transparent 设置 true 开启透明
    const material3 = new THREE.MeshBasicMaterial({
      color: colors,
      side: THREE.DoubleSide,
      transparent: true,
    });
    littleCircleRing = new THREE.Mesh(geometry3, material3);
    // 绘制地图时 y轴取反 这里同步
    littleCircleRing.position.set(x0, z0, y0);
    littleCircleRing.scale.set(2, 2, 1);
    littleCircleRing.rotation.x = -0.5 * Math.PI;
    littleCircleRing.layers.enable(1);
    sence.add(littleCircleRing);
  };

  // 光点柱 光柱
  const dotBarlight = (posStart, colors, height, message) => {
    // 设置光点柱的起始位置，包括x、y、z坐标
    const [x0, y0, z0] = [...posStart, 5 + height / 2];
    AnmiRingGeometry([x0, y0], colors);  // 调用 AnmiRingGeometry 函数创建一个环形的动画效果
    // var geometry = new THREE.ConeBufferGeometry(0.25, 3.5, 5);  // 创建圆锥几何体，作为光点柱的主体
    var geometry = new THREE.CylinderBufferGeometry(0.25, 0.25, 3 + height, 5); // 创建圆柱几何体，作为光点柱的主体
    var material1 = new THREE.MeshBasicMaterial({  // 创建材质，设置颜色，并使其半透明
      color: colors,
      transparent: true,
      opacity: 0.4,
    });
    var cylinder = new THREE.Mesh(geometry, material1);  // 创建圆锥网格
    cylinder.position.set(x0, z0, y0);  // 设置圆锥网格的位置

    cylinder.layers.enable(1);  // 启用图层，以便在渲染时使用
    sence.add(cylinder);  // 将圆锥网格添加到场景中
    render();
  };

  // tween 动画 相机轨迹动画 相机动画
  const CameraAnmition = () => {
    var tweena = cameraCon(
      { x: 89.67626699596627, y: 107.58058095557215, z: 51.374711690741705 },
      { x: 89.67626699596627, y: 107.58058095557215, z: 51.374711690741705 },
      300,
    );
    var tweenb = cameraCon(
      { x: 89.67626699596627, y: 107.58058095557215, z: 51.374711690741705 },
      { x: 31.366485208227502, y: 42.7325471436067, z: 26.484221462746017 },
      800,
    );
    var tweenc = cameraCon(
      { x: 31.366485208227502, y: 42.7325471436067, z: 26.484221462746017 },
      { x: 32.19469382023058, y: 22.87664020700182, z: 27.742681212371384 },
      1000,
    );

    tweena.chain(tweenb);
    tweenb.chain(tweenc);
    tweena.start();
  };


  // 相机运动动画函数
  function cameraCon(
    // 起始位置，默认为原点
    p1 = { x: 0, y: 0, z: 0 },
    // 目标位置，默认为 (30, 30, 30)
    p2 = { x: 30, y: 30, z: 30 },
    // 运动持续时间，默认为 6000 毫秒
    time = 6000,
  ) {
    // 创建 Tween 动画实例，从 p1 运动到 p2，持续时间为 time
    var tween1 = new TWEEN.Tween(p1)
      .to(p2, time || 200000) // 设置目标值和持续时间
      .easing(TWEEN.Easing.Quadratic.InOut); // 设置缓动函数为 Quadratic.InOut

    // 更新相机位置函数
    var update = function () {
      camera.position.set(p1.x, p1.y, p1.z); // 设置相机位置为当前 tween 的值
    };

    // 在 tween 更新时执行更新相机位置函数
    tween1.onUpdate(update);

    // 返回 Tween 动画实例
    return tween1;
  }



  const clock = new THREE.Clock();
  // 动画函数
  function renderanmi() {
    // 获取时间增量
    const dt = clock.getDelta();
    // 更新Tween动画
    TWEEN.update();
    // 更新控制器
    controls.update();
    // 渲染场景
    render();

    // 渲染标签
    if (css2dRender) {
      css2dRender.render(sence, camera)
    }

    // 点击地图
    if (meshArea) {

      // TODO 又一次点击新的（已经存在老的，需要还原meshOld的材质和位置）（同时，改变新的材质和位置）
      if (meshArea != meshOld && meshFlag == 1 && meshOld.position.y > 2.1) {
        meshOld.position.y = 2;
        meshOld.material = materialDeepBlue;
        meshArea.position.y = 2.11;
        meshArea.material = materialBlue;
      }

      // 第一次点击新的  （改变材质 & 高度上升到2.4）
      if (meshArea.position.y < 2.2 && meshFlag == 0) {
        var now = performance.now(); // 获取当前时间  
        var elapsed = now - startTime; // 计算已过去的时间  
        var progress = Math.min(elapsed / duration, 1); // 计算过渡的进度（0到1之间）  
        var easedProgress = progress; // 例如，可以使用cubic-in-out等easing函数  
        // 根据进度计算新的y位置  
        let newY = meshArea.position.y + amountToRaise * easedProgress;
        meshArea.position.y = newY;   // 位置
        meshArea.material = materialBlue;  // 材质
        meshFlag = 1;  // 变为其他点击
      }

      // TODO 再一次点击自身（如果meshOld是自己，把高度和材质还原到之前的）高度下降到2
      if (meshFlag == 2) {
        meshArea.position.y = 2;
        meshArea.material = materialDeepBlue;
        meshFlag = 0;  // 变为第一次點擊
        meshArea = null
      }


      meshOld = meshArea
    }

    // 在渲染循环中更新文字网格的朝向
    updateTextOrientation(camera);

    // 更新对象的旋转
    half_circle_blue_.rotation.z += 0.03; // 调整旋转速度
    blue_bottom_circle.rotation.z += 0.03; // 调整旋转速度

    // 请求下一帧动画
    window.requestAnimationFrame(renderanmi);
  }

  // 渲染
  const render = () => {
    sence.traverse(darkenNonBloomed2);
    // 2. 用 bloomComposer 产生辉光
    bloomComposer.render();
    // 3. 将转成黑色材质的物体还原成初始材质
    sence.traverse(restoreMaterial);
    // 4. 用 finalComposer 作最后渲染
    finalComposer.render();
  };
  const darkenNonBloomed2 = (obj) => {
    const material = obj.material;
    if (material && bloomLayer.test(obj.layers) === false) {
      materials[obj.uuid] = material;
      if (!darkMaterials[material.type]) {
        const Proto = Object.getPrototypeOf(material).constructor;
        darkMaterials[material.type] = new Proto({ color: 0x000000 });
      }
      obj.material = darkMaterials[material.type];
    }
  };

  const restoreMaterial = (obj) => {
    if (materials[obj.uuid]) {
      obj.material = materials[obj.uuid];
      delete materials[obj.uuid];
    }
  };
  return { initMaps, setMapDom, setmapborder };
}

export default Render3DMode;
